package com.ruoyi.wetest.stats;

import com.codahale.metrics.*;
import org.apache.lucene.util.RamUsageEstimator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author Allen
 * @description TODO
 * @Date 2024/5/16 17:51
 */
public class WeTestUniformReservoir implements Reservoir {

    private static final int DEFAULT_SIZE = 1028;
    private static final int BITS_PER_LONG = 63;
    private final AtomicLong count = new AtomicLong();
    private final ArrayList<Long> values;
    private int startIdx = 0;
    private int endIdx = 0;
    private long lastTime = 0l;
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * Creates a new {@link UniformReservoir} of 1028 elements, which offers a 99.9% confidence level
     * with a 5% margin of error assuming a normal distribution.
     */
    public WeTestUniformReservoir() {
        this(DEFAULT_SIZE);
    }

    /**
     * Creates a new {@link UniformReservoir}.
     *
     * @param size the number of samples to keep in the sampling reservoir
     */
    public WeTestUniformReservoir(int size) {
        this.values = new ArrayList<Long>(size);
        count.set(0);
    }

    @Override
    public int size() {
        final long c = count.get();
        synchronized (this) {
            if (c > values.size()) {
                return values.size();
            }
        }
        return (int) c;
    }

    @Override
    public void update(long value) {
        count.incrementAndGet();
        synchronized (this) {
            values.add(value);
            long l = System.currentTimeMillis();
            if (lastTime == 0) {
                lastTime = l;
            } else {
                long l1 = l - lastTime;
                if (l1 >= 5000) {
                    //logger.error("update l1:{}",l1);
                    startIdx = endIdx;
                    endIdx = values.size() - 1;
                    this.lastTime=l;
                }
            }
        }

    }

    /**
     * 根据区间获取快照
     * @return
     */
    public Snapshot getSnapshot2() {
        synchronized (this) {
            if (endIdx > 0) {
                List<Long> longs = values.subList(startIdx, endIdx);
                logger.error("getSnapshot2 size:{},startIdx:{},endIdx:{}", longs.size(), startIdx, endIdx);
                long[] copy = new long[longs.size()];
                for (int i = 0; i < longs.size(); i++) {
                    copy[i] = longs.get(i);
                }
                return new UniformSnapshot(copy);
            }
            return null;
        }
    }

    @Override
    public Snapshot getSnapshot() {
        synchronized (this) {
            final int s = size();
            long[] copy = new long[s];
            for (int i = 0; i < s; i++) {
                copy[i] = values.get(i);
            }
            return new UniformSnapshot(copy);
        }
    }

    /**
     * 内存占用内存大小
     * @return
     */
    private long getMemSize() {
        return RamUsageEstimator.sizeOf(values);
    }
}
